/*
 *  Fighter.cpp
 *  
 *	Version 1.0
 *  Created by Nicholas Blecha on 9/25/10.
 *  Copyright 2010 Michigan Technological University. All rights reserved.
 *
 */

#include "Fighter.h"

#define DELAY_MULT 20

Fighter::Fighter(int spd, int hp, int pow)
{
	/*if (spd<=0 || hp<=0 || pow<=0) {
		throw "At least one argument is less than or equal to 0.";
	}*/
	maxHitPoints = 100;
	power = pow;
	maxSpeed = spd;
	speed = 0;
	angle = 0;
	maxRotVel = (float)(M_PI/32);
	turnDir=NEUTRAL;
	forwardDir=NEUTRAL;
	rotationalVel=0;
	mercyCount=0;
	mercyHide = false;
	
	controlledBeams[0]=NULL;
	boost=NULL;
	boostID=0;
	shield=NULL;
	shieldID=0;
	
	initialPosition=NULL;
	lives = 1;
	
	shielded=false;

	hitPoints = maxHitPoints;
	normal = new StandardNormalAttack(this);
	wide = new StandardWideAttack(this);
	special = new MissileAttack(this);
	drawPos = new SDL_Rect();

	hitbox = new Hitbox(65, 60, 36, 50);
	radius = 64;
}

void Fighter::initializeBeams() {
	if (controlledBeams[0]==NULL) {
		for (int i=0; i<BEAM_LIMIT; i++)
			controlledBeams[i] = new Beam(rnd, i);
	}
}

void Fighter::initializeExtras() {
	if (boost==NULL) {
		boost = rnd->loadImage("Images//Thrust.png");
		boostID = rnd->createTexture(boost);
	}
	if (shield==NULL) {
		shield = rnd->loadImage("Images//Shield.png");
		shieldID = rnd->createTexture(shield);
	}
}

int Fighter::getSpeed() {
	return speed;
}

int Fighter::getPower() {
	return power;
}

int Fighter::getMaxHP() {
	return maxHitPoints;
}

int Fighter::getHP() {
	return hitPoints;
}


int Fighter::dmg(int d) 
{
	hitPoints -= d;
	if (hitPoints>maxHitPoints) {
		hitPoints = maxHitPoints;
	}
	return hitPoints;
}

void Fighter::turnLeft() {
	turnDir = LEFT;
}

void Fighter::turnRight()  {
	turnDir = RIGHT;
}

void Fighter::stopTurn() {
	turnDir = NEUTRAL;
}

void Fighter::accelerateForward() {
	forwardDir=FORWARD;
}

void Fighter::accelerateBackward() {
	forwardDir=BACKWARD;
}

void Fighter::brake() {
	forwardDir=NEUTRAL;
}

Beam* Fighter::getNewBeam() {
	for (int i=0; i<BEAM_LIMIT; i++) {
		if (!controlledBeams[i]->isActive()) {
			return controlledBeams[i];
		}
	}
	return NULL;
}

Beam* Fighter::getBeam(int i)
{
	for(int b=0; b<BEAM_LIMIT; b++)
	{
		if(controlledBeams[b] != NULL)
		{
			if(controlledBeams[b]->getID() == i)
				return controlledBeams[b];
		}
	}

	return NULL;
}

void Fighter::setPos(int a, int b){
	position.x = a;
	position.y = b;
	if (initialPosition==NULL) {
		initialPosition = new SDL_Rect();
		initialPosition->x = a;
		initialPosition->y = b;
	}
}

bool Fighter::respawn()  {
	if (lives>0) {
		lives--;
		setPos(initialPosition->x, initialPosition->y);
		hitPoints = maxHitPoints;
		special->addUses(special->getMaxUses());
		setMercy(2.0);
		return true;
	}
	return false;
}

void Fighter::moveFighter(Uint32 ticks) 
{
	if(mercyTimer.isStarted())
	{
		mercyCount -= (mercyTimer.getTicks()/1000.0);
		if(mercyCount <= 0)
		{
			mercyCount = 0;
			mercyHide = false;
			mercyTimer.stop();
		}

		if(mercyTimer.getTicks() >= BLINK_MS_DELAY)
		{
			mercyHide = !(mercyHide);
			mercyTimer.start();
		}
	}

	if (hitPoints > 0) 
	{
		switch (forwardDir) {
			case FORWARD:
				if (maxSpeed/stepsToFullSpeed < 0)
					speed -= maxSpeed/stepsToFullSpeed;
				else {
					speed--;
				}

			if (speed< -maxSpeed) {
				if (maxSpeed/stepsToFullSpeed > 0)
					speed = -maxSpeed;
				else {
					speed++;
				}

			}
			break;
		case BACKWARD:
			speed += maxSpeed/stepsToFullSpeed;
			if (speed>maxSpeed) {
				speed = maxSpeed;
			}
			break;
		case NEUTRAL:
				if (abs(speed/stepsToFullSpeed)>0)
					speed-=speed/stepsToFullSpeed;
				else {
					if (speed>0)
						speed--;
					else if (speed<0)
						speed++;
				}
			break;
		default:
			break;
	}

	switch (turnDir) {
		case LEFT:
			rotationalVel -= (float)(M_PI/128);
			if (rotationalVel < -maxRotVel)
				rotationalVel = -maxRotVel;
			break;
		case RIGHT:
			rotationalVel += (float)(M_PI/128);
			if (rotationalVel > maxRotVel)
				rotationalVel = maxRotVel;
			break;
		case NEUTRAL:
			
			if (rotationalVel>0) {
				rotationalVel -= (float)(M_PI/128);
			} else if (rotationalVel<0) {
				rotationalVel+=(float)(M_PI/128);
			}
			rotationalVel=0;
			break;

		default:
			break;
	}
	
	angle += (ticks/1000.f)*(rotationalVel*DELAY_MULT);						//Need to adjust speeds (multiplied by 12 so it moves faster, temporary)
																	//This is calculating the velocity per second
	int dY = (int) ((ticks/1000.f)*(DELAY_MULT*(speed * sin(angle+M_PI/2))));
	int dX = (int) ((ticks/1000.f)*(DELAY_MULT*(speed * cos(angle+M_PI/2)))); 

	if (logic->validMove(this, dX, dY, angle)) {
			position.x += dX;
			position.y += dY;
	}
	for (int i=0; i<BEAM_LIMIT; i++) 
	{
		if (controlledBeams[i]->isActive()) 
		{
			controlledBeams[i]->autoMove(ticks);
			if (!logic->validMove(controlledBeams[i], 0, 0, 0)) {
				controlledBeams[i]->setActive(false);
			}
		}
	}
}
}

void Fighter::show(int mapX, int mapY) 
{
	drawPos->x=position.x-mapX;
	drawPos->y=position.y-mapY;
	if(hitPoints > 0 && !mercyHide){
		if (boostID!=0 && forwardDir==FORWARD) {
			rnd->drawSurface(drawPos, radiansToDegrees(angle), boostID);
		}
		rnd->drawSurface(drawPos, radiansToDegrees(angle), texId);
		if (shieldID!=0 && shielded) {
			rnd->drawSurface(drawPos, radiansToDegrees(angle), shieldID);
		}
	}

	for (int i=0; i<BEAM_LIMIT; i++) 
	{
		if (controlledBeams[i]->isActive())
			controlledBeams[i]->show(mapX, mapY);
	}
}

Attack* Fighter::getNormalAttack() {
	return normal;
}

Attack* Fighter::getWideAttack() {
	return wide;
}

Attack* Fighter::getSpecialAttack() {
	return special;
}

Fighter::~Fighter() 
{
	delete hitbox;

	SDL_FreeSurface(image);
	SDL_FreeSurface(boost);

	for(int i=0; i<BEAM_LIMIT; i++)
		delete controlledBeams[i];
	if (normal!=NULL)
		delete normal;
	if (wide!=NULL)
		delete wide;
	if (special!=NULL)
		delete special;
	if (drawPos !=NULL)
		delete drawPos;
	if (initialPosition!=NULL) {
		delete initialPosition;
	}
}

